package com.probiz.estore.core.filter;

import java.io.IOException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.jstl.core.Config;

import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import com.probiz.estore.Constants;
import com.probiz.estore.common.helper.ConfigUtil;
import com.probiz.estore.core.datasource.DbContextHolder;

/**
 * Filter to wrap request with a request including user preferred locale.
 * <P>
 * 对于单语言版本，只要设置默认的Locale即可，就是说用户无法选择。前台后台可以有不同的设置（通过系统配置）。
 * <P>
 * 现在不再支持数据的多国语言；但是对于操作界面还是支持多套的，具体支持那些，开发的时候基本确定；当然以后添加多国语言包也可以；所以通过配置控制即可，不需要复杂的管理
 * <P>
 * 扩展：可以考虑和模板包对应的。
 */
public class LocaleFilter extends OncePerRequestFilter {

	private final Map<String, Locale> supportedLocaleMap = new HashMap<String, Locale>();
	
	private Locale systemLocale;

	@Override
	public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {

		Locale preferredLocale = null;
		/**
		 * we use urlrewrite to support i18n features, so get locale from uri in first priority
		 */
		/** 如果通过参数请求切换语言，优先级最高 */
		String localeCode = request.getParameter(Constants.PREFERRED_LOCALE);
		if (localeCode != null) {
			preferredLocale = getLocaleByCode(localeCode);
		}
		
		HttpSession session = request.getSession(true);
		/**
		 * 否则如果取session储存的语言（如果有意味着已经处理过）；如果没有则取用户浏览器语言；如果不支持，取系统语言
		 */
		Locale localeInSession = (Locale) session.getAttribute(Constants.PREFERRED_LOCALE_KEY);
		if (preferredLocale == null) {
			preferredLocale = localeInSession;
			// 第一次处理，session里面还没有保存；否则preferredLocale == localeInSession
			if (preferredLocale == null) {
				/** 如果用户浏览器的语言可以支持则使用用户的设置；否则用系统缺省语言 */
				preferredLocale = request.getLocale();
				if (!isLocaleSupported(preferredLocale)) {
					preferredLocale = systemLocale;
				}
			}
		}
		
		// 到此preferredLocale非空；所以如果与session的不同（用!=即可，见上面解释），需要保存到session
		if (preferredLocale != localeInSession) {
			// 为fmt tag在session保存locale，其key可以在Constants.PREFERRED_LOCALE_KEY取得 因为实际上是session.setAttribute(name + SESSION_SCOPE_SUFFIX, value)，SESSION_SCOPE_SUFFIX=".session"
			Config.set(session, Config.FMT_LOCALE, preferredLocale);
			logger.debug("Save/update user preferred locale in session: " + preferredLocale.toString());
		}

		/** 疑问：这里直接修改传入的request参数会不会有问题？ */
		if (!(request instanceof LocaleRequestWrapper)) {
			request = new LocaleRequestWrapper(request, preferredLocale);
			ProbizLocaleContextHolder.setLocale(preferredLocale);
			/**
			 * url rewrite cannot use request.getLocale, so set a attribute here. Also used in OSCache.
			 */
			request.setAttribute(Constants.CUR_LOCALE_CODE, preferredLocale.toString());
		}
		chain.doFilter(request, response);

	}

	public Locale getLocaleByCode(String localeCode) {
		return supportedLocaleMap.get(localeCode);
	}

	private boolean isLocaleSupported(Locale locale) {
		return supportedLocaleMap.containsValue(locale);
	}

	@Override
	protected void initFilterBean() throws ServletException {
		systemLocale = ConfigUtil.getInstance().getSystemLocale();
		supportedLocaleMap.put("zh_CN", new Locale("zh", "CN"));
		supportedLocaleMap.put("en", new Locale("en"));
	}


}
